#pragma once

//命令相关库

#include <string.h>
#include <stdio.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_console.h"
#include "argtable3/argtable3.h"

#include "esp_http_client.h"
#include "esp_log.h"
#include "cJSON.h"

#define MAX_HTTP_RECV_BUFFER 512
#define TULING_URL "http://www.tuling123.com/openapi/api"
#define TULING_KEY "d74c68462da24bf8a82f45cb58c908a2"
#define TULING_UID "32"
//static const char * __func__ = "Tuling";


/*
static void register_***();   命令注册声明
在命令组注册函数添加命令注册
命令参数结构体构造
命令处理函数
命令注册绑定函数
 */

static struct {
    struct arg_str *url;
    struct arg_str *key;        //key
    struct arg_str *user_id;    //用户id
	struct arg_str *info;		//对话信息
	struct arg_end *end;
} tuling_arg;




//私有函数
esp_err_t tuling_http_event_handler(esp_http_client_event_t *evt)
{
    switch(evt->event_id) {
        case HTTP_EVENT_ERROR:
            ESP_LOGD(__func__, "HTTP_EVENT_ERROR 错误");      //错误
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGD(__func__, "HTTP_EVENT_ON_CONNECTED 连接");   //连接
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGD(__func__, "HTTP_EVENT_HEADER_SENT 发送头");    //头发送
            break;
        case HTTP_EVENT_ON_HEADER:                      //打开头
            //ESP_LOGD(__func__, "HTTP_EVENT_ON_HEADER 打开头, key=%s, value=%s", evt->header_key, evt->header_value);
            //printf("HEADER,\t%s:%s\n", evt->header_key, evt->header_value);  //用于查看返回的头部信息
            break;
        case HTTP_EVENT_ON_DATA:                        //打开数据
            ESP_LOGD(__func__, "HTTP_EVENT_ON_DATA 打开数据, len=%d", evt->data_len);
            /* if (!esp_http_client_is_chunked_response(evt->client)) {
                // Write out data
                printf("%.*s", evt->data_len, (char*)evt->data);
            }else{
                printf("%.*s", evt->data_len, (char*)evt->data);
            } */
            printf("%.*s\n", evt->data_len, (char*)evt->data); //返回响应体内容
            break;
        case HTTP_EVENT_ON_FINISH:      //结束
            ESP_LOGD(__func__, "HTTP_EVENT_ON_FINISH");
            break;
        case HTTP_EVENT_DISCONNECTED:   //断开连接
            ESP_LOGD(__func__, "HTTP_EVENT_DISCONNECTED");
            break;
    }
    return ESP_OK;
}


void tuling_task(void *pvParameter){
    //初始化变量
    const char * key = TULING_KEY;
    const char * uid = TULING_UID;
    const char * info = "你叫什么名字";
    char post_data[250];
    uint16_t post_len=0;

    if(tuling_arg.key->count) key=tuling_arg.key->sval[0];
    if(tuling_arg.user_id->count)uid=tuling_arg.user_id->sval[0];
    if(tuling_arg.info->count)info=tuling_arg.info->sval[0];

    esp_http_client_config_t config = {
        .url = TULING_URL,                              //url地址
        .event_handler = tuling_http_event_handler,           //事件处理函数
        .method=HTTP_METHOD_POST,
    };
    esp_http_client_handle_t client = esp_http_client_init(&config);        //配置
    if(tuling_arg.url->count) esp_http_client_set_url(client,tuling_arg.url->sval[0]);
    //设置post字段数据
    post_len=sprintf(post_data,"key=%s&info=%s&userid=%s",key,info,uid);
    //printf("data:%s\nlen:%d\n",post_data,post_len); //输出post数据，用于调试
    esp_http_client_set_post_field(client, post_data,post_len);
    //printf("向发送tuling请求\n");
    //执行post请求
    esp_err_t err = esp_http_client_perform(client);
    //检测请求结果
/*     
    if (err == ESP_OK) {
        ESP_LOGI(__func__, "HTTP POST 状态 = %d, content 长度 = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(__func__, "HTTP POST 请求失败: %s", esp_err_to_name(err));
    } 
    */
    esp_http_client_cleanup(client); 
    vTaskDelete(NULL);
}


//命令处理函数 之所以额外创建命令是因为需要的堆空间比较大，担心占用mian任务堆空间较多引起离奇的bug！
static int cmd_tuling(int argc, char** argv){

    int nerrors = arg_parse(argc, argv, (void**) &tuling_arg);
    if (nerrors != 0) {
        arg_print_errors(stderr, tuling_arg.end, argv[0]);
        return 1;
    }
    //printf("创建任务tuling\n");
	xTaskCreate(&tuling_task, "tuling", 4000, &tuling_arg, 5, NULL);
    return 0;
    
    
}

//命令注册函数
void register_tuling(void){
	//参数表格式化
    tuling_arg.url = arg_str0("a",NULL, "<str>", "url地址.");
    tuling_arg.key = arg_str0("k",NULL, "<str>", "应用授权key.");
    tuling_arg.user_id = arg_str0("u",NULL, "<str>", "用户id.");
    tuling_arg.info = arg_str0(NULL,NULL, "<str>", "聊天信息.");
    tuling_arg.end = arg_end(1);
	//命令注册
	const esp_console_cmd_t cmd = {
        .command = "tl",
        .help = "图灵聊天命令行工具",
        .hint = "聊天信息",
        .func = &cmd_tuling,
        .argtable = &tuling_arg
    };
    ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}




